home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1999 March
/
EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso
/
earcd
/
-archivi
/
-recent2
/
amhelios.lha
/
AmHelios
/
bitmap24.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-31
|
6KB
|
367 lines
/* -------------------------------------------------------------------------- *\
BITMAP24.CPP
Copyright © 1997 by Jarno van der Linden
jarno@kcbbs.gen.nz
24 bit bitmap handling, including IFF24 saving
This program is Freeware, and all usual Freeware rules apply.
21 Feb 1997: Project started
\* -------------------------------------------------------------------------- */
/* -------------------------------- Includes -------------------------------- */
#include <dos/dos.h>
#include <proto/dos.h>
#include <string.h>
#include "bitmap24.h"
/* ------------------------------ Definitions ------------------------------- */
/* --------------------------------- Macros --------------------------------- */
/* -------------------------------- Typedefs -------------------------------- */
typedef UBYTE Masking;
#define mskNone 0
typedef UBYTE Compression;
#define cmpNone 0
#define cmpByteRun 1
typedef struct {
UWORD w,h;
WORD x,y;
UBYTE nPlanes;
Masking masking;
Compression compression;
UBYTE reserved1;
UWORD transparentColor;
UBYTE xAspect,yAspect;
WORD pageWidth,pageHeight;
} BitMapHeader;
/* ------------------------------ Proto Types ------------------------------- */
/* -------------------------------- Structs --------------------------------- */
/* -------------------------------- Globals --------------------------------- */
/* ---------------------------------- Code ---------------------------------- */
BitMap24::BitMap24(UWORD width_arg, UWORD height_arg)
{
error = BITMAP24_ERROR_NONE;
width = width_arg;
height = height_arg;
width += (16-(width & 15)) & 15;
bytewidth = width >> 3;
bitmap = new Colour[width*height];
if(bitmap)
memset(bitmap,0,width*height*sizeof(Colour));
else
error = BITMAP24_ERROR_NOBITMAP;
}
BitMap24::~BitMap24()
{
if(bitmap)
delete bitmap;
}
int BitMap24::GetError()
{
return error;
}
BOOL BitMap24::HasError()
{
return error != BITMAP24_ERROR_NONE;
}
char *BitMap24::GetErrorStr()
{
switch(error)
{
case BITMAP24_ERROR_NONE:
return "No error";
case BITMAP24_ERROR_NOBITMAP:
return "BitMap couldn't be allocated";
case BITMAP24_ERROR_FILEOPEN:
return "Error opening output file";
case BITMAP24_ERROR_OUTOFBOUNDS:
return "Out of bounds coordinate used";
}
return "Unknown error";
}
UWORD BitMap24::GetWidth()
{
return width;
}
UWORD BitMap24::GetHeight()
{
return height;
}
BOOL BitMap24::BoundsCheck(int x,int y)
{
if((x < 0) || (x >= width) || (y < 0) || (y >= height))
{
error = BITMAP24_ERROR_OUTOFBOUNDS;
return FALSE;
}
return TRUE;
}
void BitMap24::GetColour(Colour *c,int x,int y)
{
if(BoundsCheck(x,y))
*c = bitmap[y*width+x];
}
UBYTE BitMap24::GetRed(int x,int y)
{
if(BoundsCheck(x,y))
return bitmap[y*width+x].r;
return 0;
}
UBYTE BitMap24::GetGreen(int x,int y)
{
if(BoundsCheck(x,y))
return bitmap[y*width+x].g;
return 0;
}
UBYTE BitMap24::GetBlue(int x,int y)
{
if(BoundsCheck(x,y))
return bitmap[y*width+x].b;
return 0;
}
void BitMap24::SetColour(UBYTE r,UBYTE g,UBYTE b,int x,int y)
{
Colour *bp;
if(BoundsCheck(x,y))
{
bp = &(bitmap[y*width+x]);
bp->r = r;
bp->g = g;
bp->b = b;
}
}
void BitMap24::WriteV(BPTR fh,ULONG v)
{
FWrite(fh,&v,sizeof(v),1);
}
void BitMap24::WriteB(BPTR fh,UBYTE b)
{
FWrite(fh,&b,sizeof(b),1);
}
void BitMap24::WriteC(BPTR fh, BYTE b)
{
FWrite(fh,&b,sizeof(b),1);
}
void BitMap24::WriteP(BPTR fh,void *p,int size)
{
FWrite(fh,p,size,1);
}
void BitMap24::WriteS(BPTR fh,char *s)
{
FWrite(fh,s,strlen(s),1);
}
UBYTE BitMap24::GatherBits(int row, int c, int b, int x)
{
UBYTE *bp;
UBYTE v;
x <<= 3;
b = 1<<b;
bp = ((UBYTE *)&bitmap[row*width+x]+c);
v = (UBYTE)((*bp & b)!=0);
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
bp+=3;
v = (UBYTE)((v<<1) | ((*bp & b)!=0));
return v;
}
void BitMap24::WriteRun(BPTR fh, int row, int c, int b, int runstart, int runend)
{
int x,n;
UBYTE v;
v = GatherBits(row,c,b,runstart);
for(x=runstart; x<=runend; x+=128)
{
n = (runend-x+1);
if(n > 128)
n = 128;
WriteC(fh, (BYTE)(-(n-1)));
WriteB(fh, v);
}
}
void BitMap24::WriteDump(BPTR fh, int row, int c, int b, int runstart, int runend)
{
int xx,x,n;
for(x=runstart; x<=runend; x+=128)
{
n = (runend-x+1);
if(n > 128)
n = 128;
WriteC(fh, (BYTE)(n-1));
for(xx=0; xx<n; xx++)
WriteB(fh, GatherBits(row,c,b,xx+x));
}
}
void BitMap24::FindRun(int row, int c, int b, int start, int *runstart, int *runlength)
{
int x;
UBYTE vs,v;
*runstart = x = start;
v = GatherBits(row,c,b,x);
while(*runstart < bytewidth)
{
vs = v;
x++;
while((x < bytewidth) && ((v = GatherBits(row,c,b,x)) == vs))
x++;
if((*runlength = x-*runstart) > 2)
return;
*runstart = x;
}
}
void BitMap24::WriteBitMap(char *file)
{
BPTR fh;
BitMapHeader bmheader;
int y,c,b;
int runstart,runlength,runend;
long lastpos;
bmheader.w = width;
bmheader.h = height;
bmheader.x = 0;
bmheader.y = 0;
bmheader.nPlanes = 24;
bmheader.masking = mskNone;
bmheader.compression = cmpByteRun;
bmheader.reserved1 = 0;
bmheader.transparentColor = 0;
bmheader.xAspect = 1;
bmheader.yAspect = 1;
bmheader.pageWidth = (WORD)width;
bmheader.pageHeight = (WORD)height;
fh = Open(file,MODE_NEWFILE);
if(!fh)
{
error = BITMAP24_ERROR_FILEOPEN;
return;
}
WriteS(fh,"FORM");
WriteV(fh,0);
WriteS(fh,"ILBMBMHD");
WriteV(fh,sizeof(bmheader));
WriteP(fh,&bmheader,sizeof(bmheader));
WriteS(fh,"BODY");
WriteV(fh,0);
for(y=0; y<height; y++)
{
for(c=0; c<3; c++)
{
for(b=0; b<8; b++)
{
runend = 0;
while(runend < bytewidth)
{
FindRun(y,c,b, runend, &runstart, &runlength);
WriteDump(fh, y,c,b, runend,runstart-1);
runend = runstart+runlength;
if(runstart < bytewidth)
WriteRun(fh, y,c,b, runstart,runend-1);
}
}
}
}
lastpos = Seek(fh, 0, OFFSET_CURRENT);
if(lastpos & 1)
WriteB(fh,0);
lastpos = Seek(fh, 4, OFFSET_BEGINNING);
WriteV(fh,lastpos-Seek(fh, 0, OFFSET_CURRENT)-4);
Seek(fh, 4+4+8+4+sizeof(bmheader)+4, OFFSET_BEGINNING);
WriteV(fh, lastpos-Seek(fh, 0, OFFSET_CURRENT)-4);
Close(fh);
}